#include "ObjectManager.h"

ObjectManager m_ObjectManager;

Object ObjectManager::Error(NULL);

ObjectManager::ObjectManager()
{
	if(!Error.Attributes.Size())
	{
		Error.Attributes.Add(Value("Name","Error"));
		Error.Attributes.Add(Value("X",-1));
		Error.Attributes.Add(Value("Y",-1));
	}
}

int ObjectManager::GetSize()
{
	return Objects.Size();
}

Object &ObjectManager::operator[] (const Value &Index)
{
	return Objects[Index];
}

bool ObjectManager::AddAttributeToObject(const Value& Index, const Value& NewAttribute)
{
	if(!CheckValidIndex(Index))
		return false;

	if(strcmp(Objects[Index].Attributes[NewAttribute.name].name, "Error") != 0)
		return false;

	return Objects[Index].Attributes.Add(NewAttribute);
}

bool ObjectManager::RemoveAtttributeFromObject(const Value& Index, const Value& OldAttribute)
{
	if(!CheckValidIndex(Index))
		return false;
	if(OldAttribute.GetType() == AT_INT)
		return Objects[Index].Attributes.RemoveAtIndex(OldAttribute.ToInt());
	else if(OldAttribute.GetType() == AT_STRING)
	{
		if(strcmp(Objects[Index].GetBaseAttribute(OldAttribute).name, "Error") != 0)
		{
			for(int i = 0; i < Objects[Index].Attributes.Size(); i++)
			{
				if(strcmp(Objects[Index].Attributes[i].name, OldAttribute.ToCharPtr()) == 0)
					return Objects[Index].Attributes.RemoveAtIndex(i);
			}
		}
	}
	return false;
}

int ObjectManager::GetNumberOfAttributesFromObject(const Value &Index)
{
	if(GetBaseAttributeFromObject(Index,"Name") == "Error")
		return -1;

	return Objects[Index].Attributes.Size();
}

Value &ObjectManager::GetBaseAttributeFromObject(const Value &Index, const Value &Name)
{
	if(!CheckValidIndex(Index))
	 return *Container<Value>::Error;
	return Objects[Index].GetBaseAttribute(Name);
}

Value ObjectManager::GetModifiedAttributeFromObject(const Value &Index, const Value &Name)
{
	if(!CheckValidIndex(Index))
	 return *Container<Value>::Error;
	return Objects[Index].GetModifiedAttribute(Name);
}

bool ObjectManager::AddEffectToObject(const Value &Index, const Effect &NewEffect)
{
	if(!CheckValidIndex(Index))
		return false;

	if(strcmp(Objects[Index].Effects[NewEffect.name].name, "Error") != 0)
		return false;

	return Objects[Index].Effects.Add(NewEffect);
}

bool ObjectManager::RemoveEffectFromObject(const Value &Index, const Value &EffectIndex)
{
	if(!CheckValidIndex(Index))
		return false;
	if(EffectIndex.GetType() == AT_INT)
		return Objects[Index].Effects.RemoveAtIndex(EffectIndex.ToInt());
	else if(EffectIndex.GetType() == AT_STRING)
	{
		for(int i = 0; i < Objects[Index].Effects.Size(); i++)
		{
			if(strcmp(Objects[Index].Effects[i].name, EffectIndex.ToCharPtr()) == 0)
			{
				return Objects[Index].Effects.RemoveAtIndex(i);
			}
		}
	}
	return false;
}

int ObjectManager::GetNumberOfEffectsFromObject(const Value &Index)
{
	if(GetBaseAttributeFromObject(Index,"Name") == "Error")
		return -1;

	return Objects[Index].Effects.Size();
}

Effect &ObjectManager::GetEffectFromObject(const Value &Index, const Value &EffectIndex)
{
	if(!CheckValidIndex(Index))
		return *Container<Effect>::Error;
	return Objects[Index].Effects[EffectIndex];
}

bool ObjectManager::AddEventToObject(const Value &Index, const Event &NewEvent)
{
	if(!CheckValidIndex(Index))
		return false;

	if(strcmp(Objects[Index].Events[NewEvent.name].name, "Error") == 0)
		return false;

	return Objects[Index].Events.Add(NewEvent);
}

bool ObjectManager::RemoveEventFromObject(const Value &Index, const Value &EventIndex)
{
	if(!CheckValidIndex(Index))
		return false;

	if(EventIndex.GetType() == AT_INT)
		return Objects[Index].Events.RemoveAtIndex(EventIndex.ToInt());
	else if(EventIndex.GetType() == AT_STRING)
	{
		for(int i = 0; i < Objects[Index].Events.Size(); i++)
		{
			if(strcmp(Objects[Index].Events[i].name, EventIndex.name) == 0)
				return Objects[i].Events.RemoveAtIndex(i);
		}
	}
	return false;
}

int ObjectManager::GetNumberOfEventsFromObject(const Value &Index)
{
	if(GetBaseAttributeFromObject(Index,"Name") == "Error")
		return -1;

	return Objects[Index].Events.Size();
}

Event &ObjectManager::GetEventFromObject(const Value &Index, const Value &EventIndex)
{
	if(!CheckValidIndex(Index))
		return *Container<Event>::Error;

	return Objects[Index].Events[EventIndex];
}

bool ObjectManager::AddChildToObject(const Value &Index, const Value &ChildIndex)
{
	if(!CheckValidIndex(Index) || !CheckValidIndex(ChildIndex))
		return false;

	return Objects[Index].Children.Add(Objects[ChildIndex]);
}

bool ObjectManager::RemoveChildFromObject(const Value &Index, const Value &ChildIndex)
{
	if(!CheckValidIndex(Index) || !CheckValidIndex(ChildIndex))
		return false;

	if(ChildIndex.GetType() == AT_INT)
		return Objects[Index].Children.RemoveAtIndex(ChildIndex.ToInt());
	else if (ChildIndex.GetType() == AT_STRING)
	{
		for(int i = 0; i < Objects[Index].Children.Size(); i++)
		{
			if(Objects[Index].Children[ChildIndex].GetBaseAttribute("Name") != "Error")
			{
				Objects[Index].Children[i].Parent = NULL;
				return Objects[Index].Children.RemoveAtIndex(i);
			}
		}
	}

	return false;
}

int ObjectManager::GetNumberOfChildrenFromObject(const Value &Index)
{
	if(GetBaseAttributeFromObject(Index,"Name") == "Error")
		return -1;

	return Objects[Index].Children.Size();
}

Object &ObjectManager::GetChildFromObject(const Value &Index, const Value &ChildIndex)
{
	if(!CheckValidIndex(Index))
		return *Container<Object>::Error;
	return Objects[Index][ChildIndex];
}

bool ObjectManager::AddObject()
{
	Object NewObject;
	NewObject.Attributes.Add(Value("Name","NewObject"));
	NewObject.Attributes.Add(Value("X", -1));
	NewObject.Attributes.Add(Value("Y", -1));
	NewObject.Attributes.Add(Value("ImageIndex", -1));
	NewObject.Attributes[0] += Objects.Size();
	NewObject.Index = Objects.Size();
	return Objects.Add(NewObject);
}

bool ObjectManager::AddObject(const Object &NewObject)
{
	bool Result = Objects.Add(NewObject);
	if(Result)
		Objects[Objects.Size()-1].Index = Objects.Size()-1;
	return Result;
}

void ObjectManager::Clear()
{
	Objects.Clear();
}

bool ObjectManager::CheckValidIndex(const Value &Index)
{
	return (Objects[Index].GetBaseAttribute("Name") != "Error");
}